package me.zhengjie.modules.gis.service.impl;

import com.alibaba.fastjson.JSONArray;
import lombok.RequiredArgsConstructor;
import me.zhengjie.config.DistrictEnum;
import me.zhengjie.domain.AreaConf;
import me.zhengjie.modules.gis.domainSmart.SmartWeighbridgeData;
import me.zhengjie.modules.gis.repository.AreaConfRepository;
import me.zhengjie.modules.gis.repositorySmart.SmartWeighbridgeDataRepository;
import me.zhengjie.modules.gis.service.dto.*;
import me.zhengjie.modules.quartz.task.TestTask;
import me.zhengjie.utils.DateUtil;
import me.zhengjie.utils.StringUtils;
import me.zhengjie.utils.map.LonlatConver;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@RequiredArgsConstructor
public class GisService {

    private final TestTask task;
    public final AreaConfRepository areaConfRepository;
    private final SmartWeighbridgeDataRepository smartWeighbridgeRepository;

    private static final HashMap<String, Object> cache = new HashMap<>();

    //执行地磅地点数据的同步，使用异步操作减少接口占用
    public void syncWeighbridgeData() {
//        ExecutorService executor = Executors.newCachedThreadPool();
//        executor.submit(task::retrieveFutaiIn);
        ExecutorService executor2 = Executors.newCachedThreadPool();
        executor2.submit(task::retrieveMesArea);
    }

    //执行路径数据的同步，使用异步操作减少接口占用
    public void syncLineData() {
//        ExecutorService executor = Executors.newCachedThreadPool();
//        executor.submit(task::retrieveFutaiIn);
        ExecutorService executor2 = Executors.newCachedThreadPool();
        executor2.submit(task::setLineData);
    }

    //获取减量排放统计数据 - 通过进料统计
    public ReduceEmissionDto getGisReduceEmission(Integer year) {
        if (year == null) {
            year = Calendar.getInstance().get(Calendar.YEAR);
        }

        String start = year + "-01-01 00:00:00";
        String end = (year + 1) + "-01-01 00:00:00";
        List<SmartWeighbridgeData> inHistoryList = smartWeighbridgeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> res = new ArrayList<>();
            res.add(criteriaBuilder.notEqual(root.get("dataOperate"), "2"));
            res.add(criteriaBuilder.equal(root.get("memo"), "正常"));
            res.add(criteriaBuilder.notEqual(root.get("productName"), "空车数据"));
            res.add(criteriaBuilder.isNotNull(root.get("sourceUnit")));
            res.add(criteriaBuilder.notEqual(root.get("sourceUnit"), ""));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%空车%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%退票%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%内部%"));
            res.add(criteriaBuilder.equal(root.get("transportUnitInnerCode"), "1"));
            res.add(criteriaBuilder.between(root.get("tareTime"), DateUtil.parseDate(start, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime(),
                    DateUtil.parseDate(end, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime()));
            return criteriaQuery.where(res.toArray(new Predicate[0])).getRestriction();
        });
        //创建结果对象
        ReduceEmissionDto result = new ReduceEmissionDto();
        result.setYear(year);
        if (inHistoryList.isEmpty()) {
            return result;
        }
        HashMap<String, AreaConf> locationPositionMap = getAreaConfMap(3);
        //月度统计
        HashMap<Integer, BigDecimal> monthlyEmissionMap = new HashMap<>();
        for (int i = 1; i <= 12; i++) {
            monthlyEmissionMap.put(i, BigDecimal.ZERO);
        }
        //辖区排放量统计
        HashMap<String, BigDecimal> districtEmissionMap = new HashMap<>();
        //辖区排放项目的数量统计
        HashMap<String, HashSet<String>> districtCountMap = new HashMap<>();
        for (DistrictEnum districtEnum : DistrictEnum.values()) {
            if (!"苏州市".equals(districtEnum.getCity())) {
                continue;
            }
            districtEmissionMap.put(districtEnum.getDistrict(), BigDecimal.ZERO);
            districtCountMap.put(districtEnum.getDistrict(), new HashSet<>());
        }
        //具体地点的排放量统计
        HashMap<String, ReduceEmissionData> locationEmissionMap = new HashMap<>();

        //遍历数据
        for (SmartWeighbridgeData inHistory : inHistoryList) {
            BigDecimal emit = inHistory.getNetWeight();
            if (emit == null || emit.equals(BigDecimal.ZERO) || inHistory.getTareTime() == null) {
                continue;
            }
            Timestamp timestamp = new Timestamp(inHistory.getTareTime());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(timestamp);
            int month = calendar.get(Calendar.MONTH) + 1;
            BigDecimal mon = monthlyEmissionMap.get(month);
            if (mon != null) {
                monthlyEmissionMap.put(month, mon.add(emit));
            }

            //通过发货地点查找gps数据
            String sourceUnit = inHistory.getSourceUnit();
            AreaConf areaConf = locationPositionMap.get(sourceUnit);
            if (StringUtils.isBlank(inHistory.getArea()) && areaConf != null && StringUtils.isNotBlank(areaConf.getDistrict())) {
                inHistory.setArea(areaConf.getDistrict());
            }
            String district = inHistory.getArea() != null ? inHistory.getArea().trim().replace("-", "").replace("0", "") : "";
            if (StringUtils.equals(district, "高新区")) {
                district = "虎丘区";
                inHistory.setArea("虎丘区");
            }
            if (StringUtils.isNotBlank(district) && districtEmissionMap.containsKey(district)) {
                districtEmissionMap.put(district, districtEmissionMap.get(district).add(emit));
                if (StringUtils.equals(inHistory.getSourceUnitInnerCode(), "项目")) {
                    HashSet<String> projectSet = districtCountMap.get(district);
                    projectSet.add(inHistory.getSourceUnit());
                    districtCountMap.put(district, projectSet);
                }

            }

            if (StringUtils.isNotBlank(sourceUnit) && areaConf != null && StringUtils.isNotBlank(areaConf.getPosition())) {
                ReduceEmissionData data = locationEmissionMap.get(areaConf.getPosition());
                if (data == null) {
                    data = new ReduceEmissionData();
                    data.setDistrict(district);
                    data.setCenterPosition(areaConf.getPosition());
                    data.setLocationName(areaConf.getGisAreaName());
                    data.setEmission(BigDecimal.ZERO);
                    data.setType(5);
                }
                data.setEmission(data.getEmission().add(emit));
                locationEmissionMap.put(areaConf.getPosition(), data);
            }
        }

        //按月度排放统计
        List<ReduceEmissionData> monthlyEmissionList = new ArrayList<>();
        BigDecimal totalEmission = BigDecimal.ZERO;
        for (Map.Entry<Integer, BigDecimal> entry : monthlyEmissionMap.entrySet()) {
            ReduceEmissionData data = new ReduceEmissionData();
            data.setType(1);
            data.setMonth(String.valueOf(entry.getKey()));
            data.setEmission(entry.getValue());
            totalEmission = totalEmission.add(entry.getValue());
            monthlyEmissionList.add(data);
        }
        result.setMonthlyEmission(monthlyEmissionList);
        result.setTotalEmission(totalEmission);
        result.setDailyEmission(totalEmission.divide(BigDecimal.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_YEAR)), 2, RoundingMode.CEILING));

        //按地区排放统计
        List<ReduceEmissionData> districtEmissionList = new ArrayList<>();
        List<ReduceEmissionData> districtCountList = new ArrayList<>();
        List<ReduceEmissionData> districtAverageList = new ArrayList<>();
        int totalCount = 0;
        for (Map.Entry<String, BigDecimal> entry : districtEmissionMap.entrySet()) {
            DistrictEnum districtEnum = DistrictEnum.getByDistrictName("苏州市", entry.getKey());
            double[] gpsLoc = LonlatConver.gcj02_To_Wgs84(districtEnum.getLng().doubleValue(), districtEnum.getLat().doubleValue());
            String centerPosition = gpsLoc[0] + "," + gpsLoc[1];
            //地区排放总量
            ReduceEmissionData districtEmission = new ReduceEmissionData();
            districtEmission.setType(2);
            districtEmission.setDistrict(entry.getKey());
            districtEmission.setEmission(entry.getValue());
            districtEmission.setCenterPosition(centerPosition);
            districtEmissionList.add(districtEmission);
            //地区排放项目数量
            ReduceEmissionData districtCount = new ReduceEmissionData();
            districtCount.setType(3);
            districtCount.setDistrict(entry.getKey());
            districtCount.setProjectCount(districtCountMap.get(entry.getKey()).size());
            districtCount.setCenterPosition(centerPosition);
            districtCountList.add(districtCount);
            totalCount = totalCount + districtCountMap.get(entry.getKey()).size();
            //地区人均排放量
            ReduceEmissionData districtAverage = new ReduceEmissionData();
            districtAverage.setType(4);
            districtAverage.setDistrict(entry.getKey());
            districtAverage.setEmission(entry.getValue().divide(districtEnum.getPopulation().multiply(new BigDecimal("10000")), 2, RoundingMode.CEILING));
            districtAverage.setCenterPosition(centerPosition);
            districtAverageList.add(districtAverage);
        }
        result.setDistrictEmission(districtEmissionList);
        result.setDistrictAverageEmission(districtAverageList);
        result.setDistrictProjectCount(districtCountList);
        result.setTotalTearDownCount(totalCount);

        //按地点排放统计，从大到小排序，并且只取前20条
        List<ReduceEmissionData> locationList = new ArrayList<>(locationEmissionMap.values());
        List<ReduceEmissionData> resultLocationList = new ArrayList<>();
        if (!locationList.isEmpty()) {
            locationList.sort((o1, o2) -> o2.getEmission().compareTo(o1.getEmission()));
            for (int i = 0; i < 20 && i < locationList.size(); i++) {
                resultLocationList.add(locationList.get(i));
            }
        }
        result.setLocationEmission(resultLocationList);

        return result;
    }


    //获取收运中转的年度统计数据 - 通过进料统计
    public ReceivingDto getGisReceiving(Integer year) {
        if (year == null) {
            year = Calendar.getInstance().get(Calendar.YEAR);
        }
        String start = year + "-01-01 00:00:00";
        String end = (year + 1) + "-01-01 00:00:00";
        List<SmartWeighbridgeData> inHistoryList = smartWeighbridgeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> res = new ArrayList<>();
            res.add(criteriaBuilder.notEqual(root.get("dataOperate"), "2"));
            res.add(criteriaBuilder.equal(root.get("memo"), "正常"));
            res.add(criteriaBuilder.notEqual(root.get("productName"), "空车数据"));
            res.add(criteriaBuilder.isNotNull(root.get("sourceUnit")));
            res.add(criteriaBuilder.notEqual(root.get("sourceUnit"), ""));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%空车%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%退票%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%内部%"));
            res.add(criteriaBuilder.equal(root.get("transportUnitInnerCode"), "1"));
            res.add(criteriaBuilder.between(root.get("tareTime"), DateUtil.parseDate(start, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime(),
                    DateUtil.parseDate(end, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime()));
            return criteriaQuery.where(res.toArray(new Predicate[0])).getRestriction();
        });
        //创建结果对象
        ReceivingDto result = new ReceivingDto();
        result.setYear(year);
        if (inHistoryList.isEmpty()) {
            return result;
        }
        HashMap<String, AreaConf> locationPositionMap = getAreaConfMap(3);
        //月度统计
        HashMap<Integer, BigDecimal> monthlyReceiveMap = new HashMap<>();
        for (int i = 1; i <= 12; i++) {
            monthlyReceiveMap.put(i, BigDecimal.ZERO);
        }
        //违规企业统计
        HashMap<String, ReceivingData> violateCompanyMap = new HashMap<>();
        HashSet<String> companySet = new HashSet<>();
        HashSet<String> carNoSet = new HashSet<>();

        //具体地点的排放量统计
//        HashMap<String, LineDto> locationEmissionMap = new HashMap<>();

        //遍历数据
        for (SmartWeighbridgeData inHistory : inHistoryList) {
            BigDecimal emit = inHistory.getNetWeight();
            if (emit == null || emit.equals(BigDecimal.ZERO) || inHistory.getTareTime() == null) {
                continue;
            }
            //todo 违规企业排行 暂时无法统计 替换为运输企业统计
            String feedCompany = inHistory.getTransportUnit();//运输公司
            if (StringUtils.isNotBlank(feedCompany)) {
                ReceivingData violateData = violateCompanyMap.get(feedCompany);
                if (violateData == null) {
                    violateData = new ReceivingData();
                    violateData.setType(2);
                    violateData.setViolateCount(0);
                    violateData.setCompanyName(feedCompany);
                }
                violateData.setViolateCount(violateData.getViolateCount() + 1);
                violateCompanyMap.put(feedCompany, violateData);
                companySet.add(feedCompany);
            }

            if (StringUtils.isNotBlank(inHistory.getCarNo())) {
                carNoSet.add(inHistory.getCarNo());
            }
            Timestamp timestamp = new Timestamp(inHistory.getTareTime());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(timestamp);
            int month = calendar.get(Calendar.MONTH) + 1;
            BigDecimal mon = monthlyReceiveMap.get(month);
            if (mon != null) {
                monthlyReceiveMap.put(month, mon.add(emit));
            }
            //通过发货地点查找gps数据
            String sourceUnit = inHistory.getSourceUnit();
            AreaConf areaConf = locationPositionMap.get(sourceUnit);
            if (StringUtils.isBlank(inHistory.getArea()) && areaConf != null && StringUtils.isNotBlank(areaConf.getDistrict())) {
                inHistory.setArea(areaConf.getDistrict());
            }

            //针对详细项目地点的进料统计
//            if (StringUtils.isNotBlank(sourceUnit) && areaConf != null) {
//                LineDto data = locationEmissionMap.get(sourceUnit);
//                if (data == null) {
//                    data = new LineDto();
//                    if (StringUtils.isNotBlank(areaConf.getPosition())) {
//                        data.setPosition(areaConf.getPosition());
//                    }
////                    if (StringUtils.isNotBlank(areaConf.getLine())) {
////                        try {
////                            data.setLine(JSONArray.parseArray(areaConf.getLine(), BigDecimal[].class));
////                        } catch (Exception ignored) {}
////                    }
//                    data.setSumWeight(BigDecimal.ZERO);
//                    data.setDistrict(inHistory.getArea());
//                    data.setType(false);//true/1为出料， 0/false进料
//                }
////                List<LineContentDto> contents = data.getContent();
////                if (contents == null) {
////                    contents = new ArrayList<>();
////                }
////                LineContentDto lineContentDto = new LineContentDto();
////                lineContentDto.setEnterTime(timestamp);
////                lineContentDto.setWeight(emit);
////                lineContentDto.setStatus(false);
////                contents.add(lineContentDto);
////                data.setContent(contents);
//                data.setSumWeight(data.getSumWeight().add(emit));
//                locationEmissionMap.put(sourceUnit, data);
//            }
        }

        //按月度收运统计
        List<ReceivingData> monthlyReceiveList = new ArrayList<>();
        BigDecimal totalReceive = BigDecimal.ZERO;
        for (Map.Entry<Integer, BigDecimal> entry : monthlyReceiveMap.entrySet()) {
            ReceivingData data = new ReceivingData();
            data.setType(1);
            data.setMonth(String.valueOf(entry.getKey()));
            data.setReceive(entry.getValue());
            totalReceive = totalReceive.add(entry.getValue());
            monthlyReceiveList.add(data);
        }
        result.setMonthlyReceive(monthlyReceiveList);
        result.setTotalReceive(totalReceive);
        result.setDailyReceive(totalReceive.divide(BigDecimal.valueOf(Calendar.getInstance().get(Calendar.DAY_OF_YEAR)), 2, RoundingMode.CEILING));

        //统计运输企业 todo 违规企业无法统计，所以直接统计运输企业
        List<ReceivingData> violateList = new ArrayList<>(violateCompanyMap.values());
        List<ReceivingData> companyList = new LinkedList<>();
        if (!violateList.isEmpty()) {
            violateList.sort((o1, o2) -> o2.getViolateCount() - o1.getViolateCount());
            for (int i = 0; i < 10 && i < violateList.size(); i++) {
                companyList.add(violateList.get(i));
            }
        }
        result.setViolateCompanies(companyList);

        //按地点排放统计
//        result.setLocationReceive(new ArrayList<>(locationEmissionMap.values()));

        result.setCarCount(carNoSet.size() == 0 ? 1 : carNoSet.size());
        result.setCompanyCount(companySet.size() == 0 ? 1 : companySet.size());

        return result;
    }


    //获取循环应用的年度统计数据 - 通过出料统计
    public RecyclingDto getGisRecycling(Integer year) {
        if (year == null) {
            year = Calendar.getInstance().get(Calendar.YEAR);
        }
        String start = year + "-01-01 00:00:00";
        String end = (year + 1) + "-01-01 00:00:00";
        List<SmartWeighbridgeData> outHistoryList = smartWeighbridgeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> res = new ArrayList<>();
            res.add(criteriaBuilder.notEqual(root.get("dataOperate"), "2"));
            res.add(criteriaBuilder.equal(root.get("memo"), "正常"));
            res.add(criteriaBuilder.notEqual(root.get("productName"), "空车数据"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%空车%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%加油%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%退票%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%不装%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%退料%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%内部%"));
            res.add(criteriaBuilder.equal(root.get("transportUnitInnerCode"), "0"));
            res.add(criteriaBuilder.between(root.get("tareTime"), DateUtil.parseDate(start, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime(),
                    DateUtil.parseDate(end, DateUtil.FORMAT_YYYY_MM_DD_HH_MM_SS).getTime()));
            return criteriaQuery.where(res.toArray(new Predicate[0])).getRestriction();
        });
        //创建结果对象
        RecyclingDto result = new RecyclingDto();
        result.setYear(year);
        if (outHistoryList.isEmpty()) {
            return result;
        }
        HashMap<String, AreaConf> locationPositionMap = getAreaConfMap(2);
        //月度统计
        HashMap<Integer, BigDecimal> monthlyEmissionMap = new HashMap<>();
        for (int i = 1; i <= 12; i++) {
            monthlyEmissionMap.put(i, BigDecimal.ZERO);
        }
        //辖区排放量统计
        HashMap<String, BigDecimal> districtEmissionMap = new HashMap<>();
        for (DistrictEnum districtEnum : DistrictEnum.values()) {
            if (!"苏州市".equals(districtEnum.getCity())) {
                continue;
            }
            districtEmissionMap.put(districtEnum.getDistrict(), BigDecimal.ZERO);
        }
        //具体地点的出料统计
        HashMap<String, LineDto> locationEmissionMap = new HashMap<>();
        //具体产品的出料统计
        HashMap<String, BigDecimal> productMap = new HashMap<>();

        //遍历数据
        for (SmartWeighbridgeData outHistory : outHistoryList) {
            BigDecimal emit = outHistory.getNetWeight();
            if (emit == null || emit.equals(BigDecimal.ZERO) || outHistory.getTareTime() == null) {
                continue;
            }
            Timestamp timestamp = new Timestamp(outHistory.getTareTime());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(timestamp);
            int month = calendar.get(Calendar.MONTH) + 1;
            BigDecimal mon = monthlyEmissionMap.get(month);
            if (mon != null) {
                monthlyEmissionMap.put(month, mon.add(emit));
            }
            String district = outHistory.getArea() != null ? outHistory.getArea().trim().replace("-", "").replace("0", "") : "";
            if (StringUtils.equals(district, "高新区")) {
                district = "虎丘区";
                outHistory.setArea("虎丘区");
            }
            boolean isDistrictValid = false;
            if (StringUtils.isNotBlank(district) && districtEmissionMap.containsKey(district)) {
                isDistrictValid = true;
                districtEmissionMap.put(district, districtEmissionMap.get(district).add(emit));
            }
            //放入产品出料统计map
            if (StringUtils.isNotBlank(outHistory.getProductName()) && !StringUtils.containsAny(outHistory.getProductName(), "内部", "空车", "废")) {
                BigDecimal out = productMap.get(outHistory.getProductName());
                if (out == null) {
                    out = BigDecimal.ZERO;
                }
                productMap.put(outHistory.getProductName(), out.add(emit));
            }

            String handleUnit = outHistory.getHandleUnit();
            AreaConf areaConf = locationPositionMap.get(handleUnit);
            if (StringUtils.isNotBlank(handleUnit) && areaConf != null) {
                //如果原始数据的辖区信息无效，但是实际处置单位存在，则将area设为处置单位所在的辖区
                if (!isDistrictValid && districtEmissionMap.containsKey(areaConf.getDistrict())) {
                    district = areaConf.getDistrict();
                    districtEmissionMap.put(district, districtEmissionMap.get(district).add(emit));
                }
                //组装路径信息
                LineDto data = locationEmissionMap.get(handleUnit);
                if (data == null) {
                    data = new LineDto();
                    if (StringUtils.isNotBlank(areaConf.getPosition())) {
                        data.setPosition(areaConf.getPosition());
                    }
//                    if (StringUtils.isNotBlank(areaConf.getLine())) {
//                        try {
//                            data.setLine(JSONArray.parseArray(areaConf.getLine(), BigDecimal[].class));
//                        } catch (Exception ignored) {}
//                    }
                    data.setSumWeight(BigDecimal.ZERO);
                    data.setDistrict(district);
                    data.setStatus(0);
                    data.setType(true);//true/1为运出， 0/false运进
                }
//                List<LineContentDto> contents = data.getContent();
//                if (contents == null) {
//                    contents = new ArrayList<>();
//                }
//                LineContentDto lineContentDto = new LineContentDto();
//                lineContentDto.setEnterTime(timestamp);
//                lineContentDto.setWeight(emit);
//                lineContentDto.setStatus(false);
//                contents.add(lineContentDto);
//                data.setContent(contents);

                data.setSumWeight(data.getSumWeight().add(emit));
                locationEmissionMap.put(handleUnit, data);
            }
        }

        //按月度排放统计
        List<RecyclingData> monthlyEmissionList = new ArrayList<>();
        BigDecimal totalRecycling = BigDecimal.ZERO;
        for (Map.Entry<Integer, BigDecimal> entry : monthlyEmissionMap.entrySet()) {
            RecyclingData data = new RecyclingData();
            data.setType(1);
            data.setMonth(String.valueOf(entry.getKey()));
            data.setRecycling(entry.getValue());
            totalRecycling = totalRecycling.add(entry.getValue());
            monthlyEmissionList.add(data);
        }
        result.setMonthlyRecycling(monthlyEmissionList);
        result.setTotalRecycling(totalRecycling);

        //按地区排放统计
        List<RecyclingData> districtEmissionList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> entry : districtEmissionMap.entrySet()) {
            DistrictEnum districtEnum = DistrictEnum.getByDistrictName("苏州市", entry.getKey());
            double[] gpsLoc = LonlatConver.gcj02_To_Wgs84(districtEnum.getLng().doubleValue(), districtEnum.getLat().doubleValue());
            String centerPosition = gpsLoc[0] + "," + gpsLoc[1];
            //地区排放总量
            RecyclingData districtEmission = new RecyclingData();
            districtEmission.setType(2);
            districtEmission.setDistrict(entry.getKey());
            districtEmission.setRecycling(entry.getValue());
            if (districtEnum.getDistrict().equals("工业园区")) {
                districtEmission.setRecycling(new BigDecimal("500000000"));
            }
            districtEmission.setCenterPosition(centerPosition);
            districtEmissionList.add(districtEmission);
        }
        result.setDistrictRecycling(districtEmissionList);

        //按产品类型统计出料
        List<RecyclingData> productEmissionList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> entry : productMap.entrySet()) {
            RecyclingData productEmission = new RecyclingData();
            productEmission.setType(3);
            productEmission.setRecycling(entry.getValue());
            productEmission.setProduct(entry.getKey());
            productEmissionList.add(productEmission);
        }
        List<RecyclingData> productList = new ArrayList<>();
        if (!productEmissionList.isEmpty()) {
            productEmissionList.sort((o1, o2) -> o2.getRecycling().compareTo(o1.getRecycling()));
            for (int i = 0; i < 7 && i < productEmissionList.size(); i++) {
                productList.add(productEmissionList.get(i));
            }
        }
        result.setProductRecycling(productList);

        //按地点排放统计
        result.setLocationRecycling(new ArrayList<>(locationEmissionMap.values()));

        cache.put("recycle", result);
        return result;
    }

    /**
     * 获取最近一段时间的路线统计，按照进料/出料的数量
     *
     * @param type  路线类型 0:出料 1:进料
     * @param count 最多获取的路线数量
     * @param days  获取的天数, days = 1/null 则获取当天的
     * @return LineDto list
     */
    public List<LineDto> retrieveLatestLines(Integer type, Integer count, Integer days) {
        if (type == null || type < 0 || type > 1) {
            throw new RuntimeException("未知的类型");
        }
        //默认获取10条路线
        if (count == null || count <= 0) {
            count = 10;
        }
        if (days == null || days <= 0) {
            days = 1;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 1 - days);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        List<SmartWeighbridgeData> outHistoryList = smartWeighbridgeRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> res = new ArrayList<>();
            res.add(criteriaBuilder.notEqual(root.get("dataOperate"), "2"));
            res.add(criteriaBuilder.equal(root.get("memo"), "正常"));
            res.add(criteriaBuilder.notEqual(root.get("productName"), "空车数据"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%空车%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%内部%"));
            res.add(criteriaBuilder.notLike(root.get("sourceUnit"), "%退票%"));
            res.add(criteriaBuilder.equal(root.get("transportUnitInnerCode"), String.valueOf(type)));
            res.add(criteriaBuilder.ge(root.get("tareTime"), calendar.getTime().getTime()));
            return criteriaQuery.where(res.toArray(new Predicate[0])).getRestriction();
        });

        HashMap<String, AreaConf> locationPositionMap = getAreaConfMap(type == 0 ? 2 : 3);
        //创建结果对象
        //具体地点的排放量统计
        HashMap<String, LineDto> locationEmissionMap = new HashMap<>();
        //遍历数据
        for (SmartWeighbridgeData outHistory : outHistoryList) {
            BigDecimal emit = outHistory.getNetWeight();
            if (emit == null || emit.equals(BigDecimal.ZERO) || outHistory.getTareTime() == null) {
                continue;
            }
            String district = outHistory.getArea();
            String unitName = type == 0 ? outHistory.getHandleUnit() : outHistory.getSourceUnit();
            AreaConf areaConf = locationPositionMap.get(unitName);
            if (StringUtils.isBlank(unitName) || areaConf == null || StringUtils.isAnyBlank(areaConf.getPosition(), areaConf.getLine())) {
                continue;
            }
            if (StringUtils.equals(unitName, "苏州市建筑材料再生资源利用有限公司")) {
                continue;
            }
            //组装路径信息
            LineDto data = locationEmissionMap.get(unitName);
            if (data == null) {
                data = new LineDto();
                data.setPosition(areaConf.getPosition());
                try {
                    data.setLine(JSONArray.parseArray(areaConf.getLine(), BigDecimal[].class));
                } catch (Exception ignored) {}
                data.setSumWeight(BigDecimal.ZERO);
                data.setDistrict(district);
                data.setPositionName(unitName);
                data.setStatus(0);
                data.setType(type == 0);//true为运出， false运进
            }
            List<LineContentDto> contents = data.getContent();
            if (contents == null) {
                contents = new ArrayList<>();
            }
            LineContentDto lineContentDto = new LineContentDto();
            lineContentDto.setEnterTime(new Timestamp(outHistory.getTareTime()));
            lineContentDto.setWeight(emit);
            lineContentDto.setStatus(false);
            //确定物料类型
            if (type == 1) {
                if (StringUtils.contains(outHistory.getProductName(), "装修")) {
                    lineContentDto.setType(1);
                } else if (StringUtils.contains(outHistory.getProductName(), "拆建")) {
                    lineContentDto.setType(3);
                } else {
                    lineContentDto.setType(2);
                }
            } else {
                if (StringUtils.containsAny(outHistory.getProductName(), "废", "轻物质", "大件垃圾")) {
                    lineContentDto.setType(7);
                } else if (StringUtils.containsAny(outHistory.getProductName(), "料", "粉", "砂", "石", "渣土", "泥饼", "块")) {
                    lineContentDto.setType(5);
                } else if (StringUtils.containsAny(outHistory.getProductName(), "砼", "混凝土", "砖")) {
                    lineContentDto.setType(6);
                } else {
                    lineContentDto.setType(7);
                }
            }

            contents.add(lineContentDto);
            data.setContent(contents);
            data.setSumWeight(data.getSumWeight().add(emit));
            locationEmissionMap.put(unitName, data);
        }
        List<LineDto> lineDtos = new ArrayList<>(locationEmissionMap.values());
        //按总运输量由大到小排序
        lineDtos.sort((o1, o2) -> o2.getSumWeight().compareTo(o1.getSumWeight()));
        List<LineDto> result = new LinkedList<>();
        HashSet<String> positionSet = new HashSet<>();
        HashSet<String> nameSet = new HashSet<>();
        for (int i = 0; i < lineDtos.size(); i++) {
            if(positionSet.contains(lineDtos.get(i).getPosition()) || nameSet.contains(lineDtos.get(i).getPositionName())) {
                continue;
            } else {
                positionSet.add(lineDtos.get(i).getPosition());
                nameSet.add(lineDtos.get(i).getPositionName());
            }
            result.add(lineDtos.get(i));
            if (result.size() >= count) break;
        }

        //2024.01.16 添加常州无锡模拟数据
        List<LineDto> simulateLines = retrieveSimulateLines(type, false, null);
        result.addAll(simulateLines);

        return result;
    }


    /**
     * 获取 具体地点名 -> 路线信息的 map
     *
     * @param type 地点类型  2:出料处置单位 3:进料的拆迁项目地
     * @return
     */
    private HashMap<String, AreaConf> getAreaConfMap(Integer type) {
        List<AreaConf> areaList = areaConfRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> res = new ArrayList<>();
            if (type != null) {
                res.add(criteriaBuilder.equal(root.get("type"), type));
            }
            res.add(criteriaBuilder.isNotNull(root.get("position")));
            res.add(criteriaBuilder.notEqual(root.get("position"), ""));
            return criteriaQuery.where(res.toArray(new Predicate[0])).getRestriction();
        });
        HashMap<String, AreaConf> locationPositionMap = new HashMap<>();
        for (AreaConf area : areaList) {
            if (StringUtils.isBlank(area.getPosition()) || StringUtils.isBlank(area.getLine())) {
                continue;
            }
            locationPositionMap.put(area.getGisAreaName(), area);
        }
        return locationPositionMap;
    }

    //模拟无锡常州的运输路线 type=0应用点 type=1排放点, isChangzhouSingle = true表示只查找常州的模拟数据
    public List<LineDto> retrieveSimulateLines(Integer type, boolean isChangzhouSingle, Integer maxCount) {
        List<LineDto> result = new ArrayList<>();
        if (type != 0 && type != 1) {
            return result;
        }
        if (maxCount == null || maxCount <= 0) {
            maxCount = 15;
        }
        List<AreaConf> areaList = areaConfRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            //封装and查询条件
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.isNotNull(root.get("position")));
            list.add(criteriaBuilder.notEqual(root.get("position"), ""));
            int type1, type2;//type1为无锡的点位类型 type2为常州的点位类型
            if (type == 0) {
                type1 = 5;
                type2 = 7;
            } else {
                type1 = 6;
                type2 = 8;
            }
            if (isChangzhouSingle) {
                list.add(criteriaBuilder.equal(root.get("type"), type2));
                return criteriaQuery.where(list.toArray(new Predicate[0])).getRestriction();
            }
            Predicate[] predicates = new Predicate[list.size()];
            Predicate predicateWhere = criteriaBuilder.and(list.toArray(predicates));
            //封装or查询条件
            List<Predicate> listType = new ArrayList<>();

            listType.add(criteriaBuilder.equal(root.get("type"), type1));
            listType.add(criteriaBuilder.equal(root.get("type"), type2));
            Predicate[] predicatesPermissionArr = new Predicate[listType.size()];
            Predicate predicatesPermission = criteriaBuilder.or(listType.toArray(predicatesPermissionArr));
            //两条件合并
            return criteriaQuery.where(predicateWhere, predicatesPermission).getRestriction();
        });

        int count = 0;
        for (AreaConf areaConf : areaList) {
            LineDto data = new LineDto();
            data.setPositionName(areaConf.getGisAreaName());
            data.setPosition(areaConf.getPosition());
            try {
                data.setLine(JSONArray.parseArray(areaConf.getLine(), BigDecimal[].class));
            } catch (Exception ignored) {
            }
            data.setSumWeight(BigDecimal.valueOf(50000));
            data.setDistrict(areaConf.getDistrict());
            data.setStatus(0);
            data.setType(type == 0);//true为运出， false运进

            List<LineContentDto> contents = data.getContent();
            if (contents == null) {
                contents = new ArrayList<>();
            }
            LineContentDto lineContentDto = new LineContentDto();
            lineContentDto.setEnterTime(new Timestamp(System.currentTimeMillis()));
            lineContentDto.setWeight(BigDecimal.valueOf(50000));
            lineContentDto.setStatus(false);
            //确定物料类型
            if (type == 1) {
                lineContentDto.setType(count % 3 + 1);
            } else {
                lineContentDto.setType(count % 3 + 5);
            }
            contents.add(lineContentDto);
            data.setContent(contents);
            result.add(data);
            count++;
            if (count >= maxCount) {
                break;
            }
        }
        return result;
    }


    //常州特供版
    public List<LineDto> retrieveChangzhouLines(Integer type, Integer count, Integer days) {
        if (type == null || type < 0 || type > 1) {
            throw new RuntimeException("未知的类型");
        }
        return retrieveSimulateLines(type, true, count);
    }

    //立即同步事业部地磅数据的地点
    public void retrieveTransArea() {
        ExecutorService executor2 = Executors.newCachedThreadPool();
        executor2.submit(task::retrieveTransArea);
    }

    public Object getCache(String key) {
        return cache.get(key);
    }

}
